﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Web;
using System.Web.UI;

namespace UOL.PagSeguro {

    [AspNetHostingPermission(System.Security.Permissions.SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
    [Description("Possibilita efetuar uma venda através do UOL PagSeguro")]
    [DefaultProperty("EmailCobranca")]
    [Designer(typeof(Design.VendaPagSeguroDesigner))]
    public class VendaPagSeguro : Control {

        private static readonly string ENCODING = "iso-8859-1";

        private Comportamento _comportamento;
        private string _codigoReferencia;
        private string _emailCobranca;
        private string _moeda;
        private TipoCarrinho _tipoCarrinho;
        private TipoFreteVenda _tipoFrete;
        private double _extras;
        private Cliente _cliente;
        private List<Produto> _produtos;
        private string _urlPagSeguro;

        #region Propriedades
        /// <summary>
        /// Informa o comportamento do controle na submissão da venda.
        /// Se NovaPagina, uma nova janela do navegador será aberta. Se Redirect, a página será redirecionada para a página do PagSeguro
        /// </summary>
        public Comportamento Comportamento {
            get { return _comportamento; }
            set { _comportamento = value; }
        }
        /// <summary>
        /// Código identificador para seu site.
        /// Este campo é livre e poderá ser usado para identificar um cliente (cliente ID), o nº do pedido ou qualquer outra referência.
        /// Máximo de Caracteres: 200
        /// </summary>
        public string CodigoReferencia {
            get { return _codigoReferencia; }
            set { _codigoReferencia = value; }
        }
        /// <summary>
        /// Informar aqui o seu e-mail cadastrado e verificado pelo PagSeguro.
        /// Máximo de Caracteres: 200
        /// </summary>
        public string EmailCobranca {
            get { return _emailCobranca; }
            set { _emailCobranca = value; }
        }

        /// <summary>
        /// Formato da moeda utilizada pelo PagSeguro - BRL. Por enquanto, o PagSeguro aceita apenas pagamento em moeda brasileira (Real).
        /// Valor Padrão: BRL
        /// Máximo de Caracteres: 3
        /// </summary>
        public string Moeda {
            get { return _moeda; }
            set { _moeda = value; }
        }

        /// <summary>
        /// Tipo de POST que está sendo enviado ao PagSeguro.
        /// </summary>
        public TipoCarrinho TipoCarrinho {
            get { return _tipoCarrinho; }
            set { _tipoCarrinho = value; }
        }

        /// <summary>
        /// Tipo do Frete a ser aplicado aos produdos com frete informado
        /// </summary>
        public TipoFreteVenda TipoFrete {
            get { return _tipoFrete; }
            set { _tipoFrete = value; }
        }

        /// <summary>
        /// Utilize este campo para acrescentar ao pedido um valor adicional, caso necessário.
        /// Exemplo: você pode incluir o valor da embalagem de presente.
        /// Você também pode enviar um valor negativo neste campo, caso deseje oferecer um desconto ao seu cliente.
        /// </summary>
        public double Extras {
            get { return _extras; }
            set { _extras = value; }
        }

        /// <summary>
        /// Dados do Cliente
        /// Campo Opcional
        /// </summary>
        public Cliente Cliente {
            get { return _cliente; }
            set { _cliente = value; }
        }

        /// <summary>
        /// Lista de produtos para esta venda
        /// </summary>
        public List<Produto> Produtos {
            get { return _produtos; }
            set { _produtos = value; }
        }

        /// <summary>
        /// URL para efetuar a venda do pagseguro
        /// </summary>
        public string UrlPagSeguro {
            get { return _urlPagSeguro; }
            set { _urlPagSeguro = value; }
        }
        #endregion

        public VendaPagSeguro() {
            this._moeda = "BRL";
            this._tipoCarrinho = TipoCarrinho.CarrinhoProprio;
            this._tipoFrete = TipoFreteVenda.DefinidoPeloCliente;
            this._comportamento = Comportamento.Redirecionar;
            this._produtos = new List<Produto>();
            this._urlPagSeguro = Resources.PagSeguro_Venda;
        }

        public VendaPagSeguro(string emailCobranca)
            : this() {
            this._emailCobranca = emailCobranca;
        }

        public void Executar(System.Web.HttpResponse response) {
            response.ContentEncoding = Encoding.GetEncoding(VendaPagSeguro.ENCODING);

            StringBuilder sb = new StringBuilder();
            sb.Append("<html>");
            sb.Append("<head>");
            sb.AppendFormat("<meta http-equiv=\"content-type\" content=\"text/html; charset={0}\">", response.ContentEncoding.BodyName);
            sb.Append("</head>");
            sb.Append("<body onLoad=\"document.forms[0].submit()\">");
            sb.AppendFormat("<form name=\"formPagSeguro\" target=\"" + (this.Comportamento == Comportamento.Redirecionar ? "_self" : "PagSeguro") + "\" action=\"{0}\" method=\"post\">", this._urlPagSeguro);
            sb.AppendFormat("<input type=\"hidden\" name=\"{0}\" value=\"{1}\">", "encoding", response.ContentEncoding.BodyName);

            NameValueCollection parametros = this.GetParametros();
            foreach (string chave in parametros.AllKeys) {
                sb.AppendFormat("<input type=\"hidden\" name=\"{0}\" value=\"{1}\">", chave, HttpUtility.HtmlEncode(parametros[chave]));
            }

            sb.Append("</form>");
            sb.Append("</body>");
            sb.Append("</html>");
            response.Write(sb.ToString());
            if (this.Comportamento == Comportamento.Redirecionar) {
                response.End();
            }
        }

        public NameValueCollection GetParametros() {
            NameValueCollection nvc = new NameValueCollection();
            nvc.Add("ref_transacao", this.CodigoReferencia);
            nvc.Add("email_cobranca", this.EmailCobranca);
            nvc.Add("moeda", this.Moeda);
            nvc.Add("extras", Convert.ToString(Convert.ToInt32(this.Extras * 100)));
            
            switch (this.TipoCarrinho) {
                case TipoCarrinho.CarrinhoProprio:
                    nvc.Add("tipo", "CP");
                    break;
                case TipoCarrinho.CarrinhoPagSeguro:
                    nvc.Add("tipo", "CBR");
                    break;
            }

            switch (this.TipoFrete) {
                case TipoFreteVenda.Sedex:
                    nvc.Add("tipo_frete", "SD");
                    break;
                case TipoFreteVenda.PAC:
                    nvc.Add("tipo_frete", "EN");
                    break;
            }

            if (this.Cliente != null) {
                nvc.Add(this.Cliente.GetParametros());
            }
            for (int i = 0; i < this.Produtos.Count; i++) {
                nvc.Add(this.Produtos[i].GetParametros(i + 1));
            }
            return nvc;
        }

    }

    public enum Comportamento {
        NovaPagina,
        Redirecionar
    }

    public enum TipoCarrinho {
        CarrinhoProprio,
        CarrinhoPagSeguro
    }

    public enum TipoFreteVenda {
        Sedex,
        PAC,
        DefinidoPeloCliente
    }
}
